<template>
  <view class="signature-wrapper" :style="{ backgroundColor }">
    <canvas
      :canvas-id="canvasId"
      class="signature-canvas"
      :style="{ width: width + 'rpx', height: height + 'rpx' }"
      @touchstart="onTouchStart"
      @touchmove="onTouchMove"
      @touchend="onTouchEnd"
    ></canvas>
  </view>
  </template>

<script>
export default {
  name: 'SignaturePad',
  props: {
    canvasId: { type: String, default: 'signaturePadCanvas' },
    width: { type: Number, default: 700 },
    height: { type: Number, default: 300 },
    penColor: { type: String, default: '#000000' },
    backgroundColor: { type: String, default: '#fafafa' },
    minWidth: { type: Number, default: 1.2 },
    maxWidth: { type: Number, default: 3.6 }
  },
  data() {
    return {
      ctx: null,
      isDrawing: false,
      points: [],
      lastWidth: 0,
      hasContent: false
    }
  },
  mounted() {
    this.initCanvas()
  },
  methods: {
    initCanvas() {
      this.ctx = uni.createCanvasContext(this.canvasId, this)
      this.ctx.setFillStyle(this.backgroundColor)
      this.ctx.fillRect(0, 0, this.toPx(this.width), this.toPx(this.height))
      this.ctx.draw()
    },

    toPx(rpx) {
      // uni 默认以 750rpx 作为屏宽基准
      const sys = uni.getSystemInfoSync()
      return Math.round(rpx * sys.windowWidth / 750)
    },

    onTouchStart(e) {
      const t = e.touches[0]
      const p = { x: t.x, y: t.y, time: Date.now() }
      this.points = [p]
      this.isDrawing = true
      this.hasContent = true
    },

    onTouchMove(e) {
      if (!this.isDrawing) return
      const t = e.touches[0]
      const p = { x: t.x, y: t.y, time: Date.now() }
      this.points.push(p)
      if (this.points.length < 3) {
        return
      }
      // 平滑曲线：使用中点作为二次贝塞尔控制
      const [p0, p1, p2] = this.points.slice(-3)
      const mid1 = { x: (p0.x + p1.x) / 2, y: (p0.y + p1.y) / 2 }
      const mid2 = { x: (p1.x + p2.x) / 2, y: (p1.y + p2.y) / 2 }

      const velocity = this.pointVelocity(p1, p2)
      const targetW = this.strokeWidth(velocity)
      const w = this.lastWidth ? (this.lastWidth * 0.7 + targetW * 0.3) : targetW
      this.lastWidth = w

      this.ctx.setStrokeStyle(this.penColor)
      this.ctx.setLineCap('round')
      this.ctx.setLineJoin('round')
      this.ctx.setLineWidth(w)
      this.ctx.beginPath()
      this.ctx.moveTo(mid1.x, mid1.y)
      this.ctx.quadraticCurveTo(p1.x, p1.y, mid2.x, mid2.y)
      this.ctx.stroke()
      this.ctx.draw(true)
    },

    onTouchEnd() {
      this.isDrawing = false
      this.points = []
      this.lastWidth = 0
    },

    pointVelocity(a, b) {
      const dt = Math.max(b.time - a.time, 1)
      const dx = b.x - a.x
      const dy = b.y - a.y
      const dist = Math.sqrt(dx * dx + dy * dy)
      return dist / dt
    },

    strokeWidth(v) {
      // 速度越大，线越细，做一个平滑的衰减
      const max = this.maxWidth
      const min = this.minWidth
      const k = 10
      const width = max - (max - min) * (1 - Math.exp(-k * v))
      return Math.max(min, Math.min(max, width))
    },

    clear() {
      this.ctx.clearRect(0, 0, this.toPx(this.width), this.toPx(this.height))
      this.ctx.setFillStyle(this.backgroundColor)
      this.ctx.fillRect(0, 0, this.toPx(this.width), this.toPx(this.height))
      this.ctx.draw()
      this.hasContent = false
    },

    toTempFilePath() {
      return new Promise((resolve, reject) => {
        uni.canvasToTempFilePath({
          canvasId: this.canvasId,
          quality: 1,
          success: (res) => resolve(res.tempFilePath),
          fail: reject
        }, this)
      })
    },

    hasSignature() {
      return this.hasContent
    }
  }
}
</script>

<style scoped>
.signature-wrapper {
  width: 100%;
  border: 1rpx solid #e0e0e0;
  border-radius: 10rpx;
  overflow: hidden;
}

.signature-canvas {
  display: block;
}
</style>


